package cn.gotom.core.web;

import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.StrutsStatics;

import cn.gotom.coding.EncodingUtils;
import cn.gotom.core.pojos.Right;
import cn.gotom.core.pojos.User;
import cn.gotom.core.service.RightService;
import cn.gotom.core.service.UserService;
import cn.gotom.core.web.action.MenuInf;

import com.google.inject.Inject;
import com.google.inject.Injector;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class AuthenticationInterceptor implements Interceptor
{

	private static final long serialVersionUID = 1L;
	public static final String INJECTOR_NAME = Injector.class.getName();
	protected final Logger log = Logger.getLogger(getClass());

	@Inject
	private UserService userService;
	private RightService rightService;

	public void destroy()
	{
		log.debug("destroy  " + this);
	}

	public void init()
	{
		log.debug("init  " + this);
		User user = userService.get("username", User.administrator);
		if (user == null)
		{
			user = new User();
			user.setUsername(User.administrator);
			user.setPassword("a");
			user.setName("系统管理员");
			userService.save(user);
		}
	}

	public String intercept(ActionInvocation invocation) throws Exception
	{
		ActionContext ctx = invocation.getInvocationContext();
		HttpServletRequest request = (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);
		Injector injector = (Injector) request.getServletContext().getAttribute(INJECTOR_NAME);
		rightService = injector.getInstance(RightService.class);
		userService = injector.getInstance(UserService.class);
		saveAction(invocation);
		boolean isLogin = isLogin(invocation);
		if (isLogin)
		{
			try
			{
				return invocation.invoke();
			}
			catch (Exception ex)
			{
				log.error(ex.getMessage());
				request.setAttribute("java.lang.Throwable", ex);
				return Action.ERROR;
			}
		}
		else
		{
			return Action.LOGIN;
		}
	}

	private void saveAction(ActionInvocation invocation)
	{
		try
		{
			Object action = invocation.getProxy().getAction();
			if (action instanceof MenuInf)
			{
				MenuInf a = (MenuInf) action;
				String value = action.getClass().getName();
				Right right = rightService.get("value", value);
				if (right == null)
				{
					right = new Right();
					right.setName(a.getName());
					right.setGroupName(a.getGroupName());
					right.setValue(value);
					right.setActionName(getActionName(invocation));
					right.setSort(a.getMenuSort());
					log.error(right);
					EncodingUtils.encoding(right, "gbk", "cp850");
					rightService.save(right);
				}
			}
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}

	private boolean isLogin(ActionInvocation invocation)
	{
		try
		{
			ActionContext ctx = invocation.getInvocationContext();
			HttpServletRequest request = (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);
			Map<String, Object> session = ctx.getSession();
			if (session != null && session.get(Constants.USER_SESSION_KEY) != null)
			{
				User user = (User) session.get(Constants.USER_SESSION_KEY);
				if (user != null)
				{
					return true;
				}
				else
				{
					session.remove(Constants.USER_SESSION_KEY);
					return false;
				}
			}
			Cookie[] cookies = request.getCookies();
			if (cookies != null)
			{
				for (Cookie cookie : cookies)
				{
					if (Constants.COOKIE_REMEMBERME_KEY.equals(cookie.getName()))
					{
						String value = cookie.getValue();
						if (StringUtils.isNotEmpty(value))
						{
							UserCookie userCookie = new UserCookie(value);
							User user = userService.get("username", userCookie.getUsername());
							if (user != null && user.getPassword().equals(userCookie.getPassword()))
							{
								session.put(Constants.USER_SESSION_KEY, user);
								return true;
							}
							else
							{
								setGotoURL(invocation);
								return false;
							}
						}
						else
						{
							setGotoURL(invocation);
							return false;
						}
					}
				}
				setGotoURL(invocation);
				return false;
			}
		}
		catch (Exception e)
		{
			log.error("", e);
		}
		setGotoURL(invocation);
		return false;
	}

	private void setGotoURL(ActionInvocation invocation)
	{
		invocation.getInvocationContext().getSession().put(Constants.GOING_TO_URL_KEY, getActionName(invocation));
	}

	private String getActionName(ActionInvocation invocation)
	{
		String url = "";
		String namespace = invocation.getProxy().getNamespace();
		if (StringUtils.isNotBlank(namespace) && !namespace.equals("/"))
		{
			url = url + namespace;
		}
		String actionName = invocation.getProxy().getActionName();
		if (StringUtils.isNotBlank(actionName))
		{
			url = url + "/" + actionName;
		}
		return url;
	}
}
